﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;

namespace Quest.Core.DataAccess
{
    /// <summary>
    /// 数据库访问提供者特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true)]
    internal class AccessProviderAttribute : Attribute
    {
        /// <summary>
        /// 提供者名称
        /// </summary>
        public string ProviderName { get; set; }
    }

    /// <summary>
    /// 数据库访问提供者
    /// </summary>
    internal class AccessProvider
    {
        /// <summary>
        /// 数据库访问类集合
        /// </summary>
        private static List<AccessModel> AccessList { get; set; }
        private static List<ConnectionModel> ConnectionList { get; set; }

        static AccessProvider()
        {
            ConnectionList = new List<ConnectionModel>();
            foreach (ConnectionStringSettings conn in ConfigurationManager.ConnectionStrings)
            {
                ConnectionList.Add(new ConnectionModel()
                {
                    Name = conn.Name,
                    ProviderName = conn.ProviderName.ToUpper(),
                    ConnectionString = conn.ConnectionString
                });
            }

            AccessList = new List<AccessModel>();
            var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()).Where(p => typeof(IServer).IsAssignableFrom(p));
            foreach (var item in types)
            {
                object[] objs = item.GetCustomAttributes(typeof(AccessProviderAttribute), true);
                foreach (var obj in objs)
                {
                    AccessProviderAttribute attr = obj as AccessProviderAttribute;
                    if (attr != null)
                    {
                        AccessList.Add(new AccessModel() { AccessType = item, ProviderName = attr.ProviderName });
                        break;
                    }
                }
            }
        }

        public static IServer Create(string name = "MainConnection")
        {
            var conn = ConnectionList.FirstOrDefault(w => w.Name == name);
            if (conn == null)
            {
                throw new Exception(string.Format("数据库连接字符串未配置,Name：{0}", name));
            }
            return Create(conn.ProviderName, conn.ConnectionString);
        }

        public static IServer Create(string providerName, string connectionString)
        {
            var access = AccessList.FirstOrDefault(w => w.ProviderName == providerName.ToUpper());
            if (access == null)
            {
                throw new Exception(string.Format("暂不支持该数据库访问,ProviderName：{0}", providerName));
            }
            Type t = access.AccessType;
            Assembly assembly = t.Assembly;
            var instance = assembly.CreateInstance(t.FullName) as IServer;
            instance.Init(connectionString);
            return instance;
        }
    }

    /// <summary>
    /// 数据库访问信息
    /// </summary>
    internal class AccessModel
    {
        public Type AccessType { get; set; }
        public string ProviderName { get; set; }
    }

    /// <summary>
    /// 连接字符串信息
    /// </summary>
    internal class ConnectionModel
    {
        public string Name { get; set; }
        public string ProviderName { get; set; }
        public string ConnectionString { get; set; }
    }
}
